package com.shuwen.gcdj.service.message;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shuwen.gcdj.bean.conditionMonitoring.response.IndexAlarmMessageResp;
import com.shuwen.gcdj.bean.conditionMonitoring.response.TDSensorEarlyWarningMonitorAllResp;
import com.shuwen.gcdj.bean.message.request.AlarmmessageQueryReq;
import com.shuwen.gcdj.bean.message.request.OrderMessageQueryReq;
import com.shuwen.gcdj.bean.message.request.PLCAlarmMessageManageQueryReq;
import com.shuwen.gcdj.bean.message.request.PLCAlarmMessageManageReq;
import com.shuwen.gcdj.bean.message.response.AlarmMessageResp;
import com.shuwen.gcdj.bean.message.response.OrderMessageResp;
import com.shuwen.gcdj.bean.message.response.PLCAlarmMessageResp;
import com.shuwen.gcdj.bean.structure.response.StrategyResp;
import com.shuwen.gcdj.bean.sysDictionary.request.SysDictionaryReq;
import com.shuwen.gcdj.bean.sysDictionary.response.SysDictionaryResp;
import com.shuwen.gcdj.bean.workingConditions.response.StatisticTDConditionResp;
import com.shuwen.gcdj.common.api.CommonPage;
import com.shuwen.gcdj.common.api.CommonResult;
import com.shuwen.gcdj.common.constant.Constants;
import com.shuwen.gcdj.common.util.BeanHelper;
import com.shuwen.gcdj.common.util.FieldUtil;
import com.shuwen.gcdj.entity.MsgOrdermessage;
import com.shuwen.gcdj.entity.basics.BasicsEquipment;
import com.shuwen.gcdj.mapper.mysql.basics.BasicsEquipmentMapper;
import com.shuwen.gcdj.mapper.mysql.message.MessageCenterMapper;
import com.shuwen.gcdj.mapper.mysql.sysDictionary.SysDictionaryMapper;
import com.shuwen.gcdj.mapper.tdengine.Statistic.StatisticPlcSensorMapper;
import com.shuwen.gcdj.service.BaseService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Yangx
 */
@Service
@AllArgsConstructor
@Slf4j
public class MessageCenterService extends BaseService<MessageCenterMapper, MsgOrdermessage> {
    private final MessageCenterMapper messageCenterMapper;
    private final SysDictionaryMapper sysDictionaryMapper;
    private final StatisticPlcSensorMapper statisticPlcSensorMapper;
    private final BasicsEquipmentMapper basicsEquipmentMapper;

    public CommonResult<Integer> addPlcAlarmJob() {
        SysDictionaryReq req = new SysDictionaryReq();
        req.setParentCode(Constants.PLC_EARLY_WARNING_MONITOR_POINT);
        List<SysDictionaryResp> plclist = sysDictionaryMapper.getList(req);
        if (CollectionUtils.isEmpty(plclist)) {
            return CommonResult.success(Constants.ZERO);
        }
        String fileds = String.join(",", plclist.stream().map(SysDictionaryResp::getCode).collect(Collectors.toList()));
        List<String> filedList = plclist.stream().map(SysDictionaryResp::getCode).collect(Collectors.toList());
        if (fileds == null || fileds.isEmpty()) {
            return CommonResult.success(Constants.ZERO);
        }
        List<String> trueList = plclist.stream().filter(t -> t.getValue().equals(1)).map(SysDictionaryResp::getCode).collect(Collectors.toList());
        List<String> falseList = plclist.stream().filter(t -> t.getValue().equals(0)).map(SysDictionaryResp::getCode).collect(Collectors.toList());
        String startTime = LocalDateTime.now().minusSeconds(10).format(DateTimeFormatter.ofPattern(Constants.TD_DATATIME_FORMAT));
        String endTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(Constants.TD_DATATIME_FORMAT));
        SysDictionaryReq sysDictionaryReq = new SysDictionaryReq();
        sysDictionaryReq.setParentCode(Constants.CRANE_EQUIPMENT_OBJECT);
        List<SysDictionaryResp> sysDictionaryRespList = sysDictionaryMapper.getList(sysDictionaryReq);
        sysDictionaryReq = new SysDictionaryReq();
        sysDictionaryReq.setParentCode(Constants.EQUIPMENT_CODE_TDSTABLE);
        List<SysDictionaryResp> dictionary = sysDictionaryMapper.getList(sysDictionaryReq);
        if (CollectionUtils.isEmpty(dictionary)) {
            return null;
        }
        List<PLCAlarmMessageResp> plcHistoryList = messageCenterMapper.getLastPLCAlarmMessageList(new PLCAlarmMessageManageReq());
        for (SysDictionaryResp item : sysDictionaryRespList) {
            List<PLCAlarmMessageResp> devicePlcHistoryList = plcHistoryList.stream().filter(his -> his.getEquipmentCode().equals(item.getCode())).collect(Collectors.toList());
            SysDictionaryResp tableName = dictionary.stream().filter(x -> x.getCode().contains(Constants.GANTRY_CRANE_PLC) && x.getOperateObject().equals(item.getCode())).findFirst().orElse(new SysDictionaryResp());
            BasicsEquipment basicsEquipment = basicsEquipmentMapper.selectOne(new QueryWrapper<BasicsEquipment>()
                    .lambda().eq(BasicsEquipment::getCode, item.getCode()));
            String equipmentCode = item.getCode();
            StatisticTDConditionResp tdConditionResp = new StatisticTDConditionResp();
            tdConditionResp.setSensorCode(fileds);
            tdConditionResp.setStartTime(startTime);
            tdConditionResp.setEndDateTime(endTime);
            tdConditionResp.setEqupmentCode(equipmentCode);
            tdConditionResp.setTableName(tableName.getCode());
            TDSensorEarlyWarningMonitorAllResp exceptionResp = statisticPlcSensorMapper.getPlc2ListA(tdConditionResp);
            if (exceptionResp == null) {
                continue;
            }
            List<StrategyResp> strategyResp = FieldUtil.usersBlankBoolean(filedList, TDSensorEarlyWarningMonitorAllResp.class, exceptionResp);
            strategyResp = strategyResp.stream().filter(x->x.getFLag() !=null).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(strategyResp)) {
                return CommonResult.success(Constants.ZERO);
            }
            List<StrategyResp> exceptionLists = new ArrayList<>();
            exceptionLists.addAll(strategyResp.stream().filter(strategy -> trueList.contains(strategy.getSensorCode()) && strategy.getFLag().equals(false)).collect(Collectors.toList()));
            exceptionLists.addAll(strategyResp.stream().filter(strategy -> falseList.contains(strategy.getSensorCode()) && strategy.getFLag().equals(true)).collect(Collectors.toList()));

            List<String> exceptionPoint = exceptionLists.stream().map(StrategyResp::getSensorCode).collect(Collectors.toList());
            List<String> normalPointIds = devicePlcHistoryList.stream()
                    .filter(plc -> !exceptionPoint.contains(plc.getSensorCode()))
                    .map(PLCAlarmMessageResp::getId)
                    .collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(normalPointIds)) {
                messageCenterMapper.updatePlcSignByIds(normalPointIds);
            }
            List<String> exceptionCodeList = devicePlcHistoryList.stream()
                    .filter(plc -> plc.getRemark() == null || plc.getRemark().equals(Constants.NORMAL_SIGN))
                    .map(PLCAlarmMessageResp::getSensorCode)
                    .collect(Collectors.toList());
            if(CollectionUtils.isEmpty(devicePlcHistoryList))
            {
                exceptionCodeList = exceptionPoint;
            }
            if (CollectionUtils.isEmpty(exceptionCodeList)) {
                return CommonResult.success(Constants.ONE);
            }
            List<PLCAlarmMessageResp> alarmist = new ArrayList<>();
            for (StrategyResp point : exceptionLists) {
                if (exceptionCodeList.contains(point.getSensorCode())) {
                    SysDictionaryResp sysDictionaryResp = plclist.stream().filter(e -> e.getCode().equals(point.getSensorCode())).findFirst().orElse(null);
                    PLCAlarmMessageResp alarmMessageResp = new PLCAlarmMessageResp();
                    alarmMessageResp.setEquipmentId(basicsEquipment.getId());
                    alarmMessageResp.setEquipmentName(basicsEquipment.getName());
                    alarmMessageResp.setEquipmentCode(item.getCode());
                    alarmMessageResp.setSensorCode(point.getSensorCode());
                    alarmMessageResp.setStructureId(Constants.ZERO);
                    alarmMessageResp.setStructureName("");
                    alarmMessageResp.setState(Constants.ONE);
                    String ts = String.valueOf(exceptionResp.getTs());
                    alarmMessageResp.setCreateDate(ts);
                    alarmMessageResp.setIsRead(false);
                    assert sysDictionaryResp != null;
                    String name = sysDictionaryResp.getName();
                    alarmMessageResp.setContent(MessageFormat.format(Constants.PLC_CONTENT, ts, name));
                    alarmMessageResp.setOrderCode("");
                    alarmMessageResp.setRemark(Constants.EXCEPTION_SIGN);
                    alarmist.add(alarmMessageResp);
                }
            }
            if (CollectionUtils.isEmpty(alarmist)) {
                return CommonResult.success(Constants.ONE);
            }
            if (alarmist.size() <= 1000) {
                messageCenterMapper.addBatch(alarmist);
            } else {
                int totallCount = alarmist.size();
                int pages = getCeiling(1000, totallCount);
                for (int i = 1; i <= pages; i++) {
                    List<PLCAlarmMessageResp> thisbatch = alarmist.stream().skip((i - 1) * 1000L).limit(1000).collect(Collectors.toList());
                    messageCenterMapper.addBatch(thisbatch);
                }
            }
        }


        return CommonResult.success(1);

    }

    public static Integer getCeiling(Integer count, Integer size) {
        if (count == 0 || size == 0) {
            return 0;
        }
        double value = Double.valueOf(count) / Double.valueOf(size);
        return count > 0 ? Integer.parseInt(String.valueOf(Math.ceil(value))) : 0;
    }

    public CommonResult<CommonPage<AlarmMessageResp>> getAlarmMessagePage(AlarmmessageQueryReq req) {
        Page<AlarmMessageResp> page = new Page<>(req.getPageNum(), req.getPageSize(), true);
        IPage<AlarmMessageResp> allList = messageCenterMapper.getAlarmMessagePage(page, req);
        List<AlarmMessageResp> res = allList.getRecords();
        Page<AlarmMessageResp> resPage = new Page<>(page.getCurrent(), page.getSize(), allList.getTotal());
        resPage.setRecords(res);
        return CommonResult.success(CommonPage.restPage(resPage));
    }

    public CommonResult<CommonPage<OrderMessageResp>> getOrderMessagePage(OrderMessageQueryReq req) {
        Page<OrderMessageResp> page = new Page<>(req.getPageNum(), req.getPageSize(), true);
        IPage<OrderMessageResp> allList = messageCenterMapper.getOrderMessagePage(page, req);
        List<OrderMessageResp> res = allList.getRecords();
        Page<OrderMessageResp> resPage = new Page<>(page.getCurrent(), page.getSize(), allList.getTotal());
        resPage.setRecords(res);
        return CommonResult.success(CommonPage.restPage(resPage));
    }

    public CommonResult<CommonPage<PLCAlarmMessageResp>> getPLCAlarmMessagePage(PLCAlarmMessageManageQueryReq req) {
        Page<PLCAlarmMessageResp> page = new Page<>(req.getPageNum(), req.getPageSize(), true);
        IPage<PLCAlarmMessageResp> allList = messageCenterMapper.getPLCAlarmMessagePage(page, req);
        List<PLCAlarmMessageResp> res = allList.getRecords();
        Page<PLCAlarmMessageResp> resPage = new Page<>(page.getCurrent(), page.getSize(), allList.getTotal());
        resPage.setRecords(res);
        return CommonResult.success(CommonPage.restPage(resPage));
    }

    public CommonResult<List<IndexAlarmMessageResp>> getIndexAlarmMessageList(String equipmentId) {
        int itemCount = 50;
        List<IndexAlarmMessageResp> resp = new ArrayList<>();
        AlarmmessageQueryReq alarmReq = new AlarmmessageQueryReq();
        OrderMessageQueryReq orderReq = new OrderMessageQueryReq();
        PLCAlarmMessageManageQueryReq plcReq = new PLCAlarmMessageManageQueryReq();
        BasicsEquipment equipment = basicsEquipmentMapper.selectById(equipmentId);
        if (equipment != null) {
            alarmReq.setEquipmentId(equipment.getId());
            alarmReq.setEquipmentCode(equipment.getCode());
            orderReq.setEquipmentId(equipment.getId());
            plcReq.setEquipmentCode(equipment.getCode());
        }

        Page<AlarmMessageResp> page = new Page<>(1, itemCount, true);
        Page<OrderMessageResp> orderMessageRespPage = new Page<>(1, itemCount, true);
        Page<PLCAlarmMessageResp> plcAlarmMessageRespPage = new Page<>(1, itemCount, true);
        List<AlarmMessageResp> alarmMessageResps = messageCenterMapper.getAlarmMessagePage(page, alarmReq).getRecords();
        List<IndexAlarmMessageResp> indexAlarmMessageResps = BeanHelper.copyList(alarmMessageResps, IndexAlarmMessageResp.class);
        indexAlarmMessageResps.forEach(t -> {
            t.setContent(equipment.getCode() + ":" + t.getContent());
            t.setType(3);
            t.setTypeName(Constants.INDEX_MESSAGE);
        });
        //工单预警信息
        List<OrderMessageResp> orderMessageResps = messageCenterMapper.getOrderMessagePage(orderMessageRespPage, orderReq).getRecords();
        List<IndexAlarmMessageResp> indexAlarmMessageResps1 = BeanHelper.copyList(orderMessageResps, IndexAlarmMessageResp.class);
        indexAlarmMessageResps1.forEach(t -> {
            String remark = t.getRemark() == null ? "" : t.getRemark();
            t.setContent(equipment.getCode() + ":" + remark);
            t.setEquipmentCode(t.getOrderCode());
            t.setType(Constants.TWO);
            t.setTypeName(Constants.INDEX_ORDER_ALARM_MESSAGE_TITLE);
        });
        //plc预警信息
        List<PLCAlarmMessageResp> pLCAlarmMessageResps = messageCenterMapper.getPLCAlarmMessagePage(plcAlarmMessageRespPage, plcReq).getRecords();
        List<IndexAlarmMessageResp> indexAlarmMessageRespList = BeanHelper.copyList(pLCAlarmMessageResps, IndexAlarmMessageResp.class);
        indexAlarmMessageRespList.forEach(t -> {
            t.setContent(equipment.getCode() + ":" + t.getContent());
            t.setType(Constants.ONE);
            t.setTypeName(Constants.INDEX_PLC_ALARM_MESSAGE_TITLE);
        });
        resp.addAll(indexAlarmMessageResps);
        resp.addAll(indexAlarmMessageResps1);
        resp.addAll(indexAlarmMessageRespList);
        return CommonResult.success(resp);
    }
}
